package com.nts.pmchelperdemo3.util;


import com.nts.pmchelperdemo3.entity.Machine;
import com.nts.pmchelperdemo3.entity.Scheduling;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * 机器负载计算工具类（分配任务、计算剩余容量等）
 */
public class MachineLoadUtil {

    /**
     * 按机器类型分组（磨刀机/涂层机）
     * @param machines 机器列表
     * @return 分组后的机器Map（key：类型0/1，value：机器列表）
     */
    public static Map<Integer, List<Machine>> groupMachinesByType(List<Machine> machines) {
        return machines.stream()
                .collect(Collectors.groupingBy(Machine::getMachineType));
    }

    /**
     * 计算机器当前剩余容量（最大承受量 - 已分配数量）
     * @param machine 机器
     * @param schedulings 该机器的排班记录
     * @return 剩余容量
     */
    public static int calculateRemainingCapacity(Machine machine, List<Scheduling> schedulings) {
        if (machine == null) {
            return 0;
        }

        // 已分配的总数量
        int allocated = schedulings.stream()
                .mapToInt(Scheduling::getHandleQuantity)
                .sum();

        return Math.max(0, machine.getMaxCapacity() - allocated);
    }

    /**
     * 分配任务数量到多台机器（不超过单台最大承受量）
     * @param totalQuantity 总数量
     * @param machines 可用机器列表（按负载排序）
     * @return 分配结果Map（key：机器ID，value：分配数量）
     */
    public static Map<Long, Integer> allocateQuantity(int totalQuantity, List<Machine> machines) {
        AtomicInteger remaining = new AtomicInteger(totalQuantity);
        // 按机器最大容量升序排序（优先分配给小容量机器，避免资源浪费）
        List<Machine> sortedMachines = machines.stream()
                .sorted((m1, m2) -> m1.getMaxCapacity().compareTo(m2.getMaxCapacity()))
                .collect(Collectors.toList());

        return sortedMachines.stream()
                .collect(Collectors.toMap(
                        Machine::getId,
                        machine -> {
                            int currentRemaining = remaining.get();
                            if (currentRemaining <= 0) {
                                return 0;
                            }
                            int allocate = Math.min(currentRemaining, machine.getMaxCapacity());
                            currentRemaining -= allocate;
                            return allocate;
                        }
                ))
                .entrySet().stream()
                .filter(entry -> entry.getValue() > 0) // 过滤未分配的机器
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
    }
}